package main

import (
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"time"
)

// ServerConfig 结构体用于存储从配置文件中读取的服务器配置信息。
// 结构体字段使用了 `mapstructure` 标签来指定配置文件中的字段名称。
type ServerConfig struct {
	ServiceName string `mapstructure:"name"` // 服务名称，配置文件中的字段名为 "name"
	Port        int    `mapstructure:"port"` // 服务器端口号，配置文件中的字段名为 "port"
}

func main() {
	// 创建一个新的 viper 实例，viper 用于读取配置文件
	v := viper.New()

	// 设置配置文件路径，这里指定了一个 YAML 配置文件
	v.SetConfigFile("user-web/demo/viper/viper-01/config.yaml")

	// 读取配置文件，如果读取失败则会 panic（抛出异常）
	if err := v.ReadInConfig(); err != nil {
		panic(err)
	}

	// 创建一个 ServerConfig 类型的实例，用于存储从配置文件中读取的数据
	serverConfig := ServerConfig{}

	// 将配置文件中的数据解析到 serverConfig 结构体中
	if err := v.Unmarshal(&serverConfig); err != nil {
		panic(err) // 如果解析失败，则抛出异常
	}
	// 打印解析后的 serverConfig 结构体内容
	fmt.Println(serverConfig)

	// 监控配置文件的变化，并在变化时重新加载配置
	watchConfig(v, &serverConfig)

	// 模拟服务器持续运行，保持监听配置文件变化
	for {
		time.Sleep(1 * time.Second) // 每秒检查一次配置文件
	}
}

func watchConfig(v *viper.Viper, serverConfig *ServerConfig) {
	// 监控配置文件的变化，并在变化时重新加载配置
	v.WatchConfig()

	// 配置文件变化时触发的回调函数
	v.OnConfigChange(func(e fsnotify.Event) {
		// 打印配置文件变化的信息，e.Name 是发生变化的配置文件路径
		fmt.Println("配置文件发生变化:", e.Name)

		// 重新读取配置文件内容
		_ = v.ReadInConfig()

		// 将读取到的配置文件内容反序列化到 serverConfig 结构体中
		_ = v.Unmarshal(serverConfig)

		// 打印重新加载后的配置
		fmt.Println(serverConfig)
	})

}
